\ Need to require string words for them to be available!
require string.fs


: not 0= ;

: oppo-rock s" A" ;
: oppo-paper s" B" ;
: oppo-scissors s" C" ;

: play-rock s" X" ;
: play-paper s" Y" ;
: play-scissors s" Z" ;

: rock-score 1 ;
: paper-score 2 ;
: scissors-score 3 ;

: loss-score 0 ;
: draw-score 3 ;
: win-score 6 ;

: oppo-rock? ( c-addr len -- flag ) oppo-rock compare 0= ;
: play-rock? ( c-addr len -- flag ) play-rock compare 0= ;

: oppo-paper? ( c-addr len -- flag ) oppo-paper compare 0= ;
: play-paper? ( c-addr len -- flag ) play-paper compare 0= ;

: oppo-scissors? ( c-addr len -- flag ) oppo-scissors compare 0= ;
: play-scissors? ( c-addr len -- flag ) play-scissors compare 0= ;

: rotate-5 ( n1 n2 n3 n4 n5 -- n2 n3 n4 n5 n1 )
  { a b c d e }
  b c d e a ;

: -rotate-5 ( n1 n2 n3 n4 n5 -- n2 n3 n4 n5 n1 )
  { a b c d e }
  e a b c d ;

: 4dup ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 n2 n3 n4 )
  { a b c d }
  a b c d a b c d ;

: 4drop ( n1 n2 n3 n4 -- )
  2drop 2drop ;

: draw? ( oppo-action-string len play-action-string len -- score-u )
  4dup play-rock? -rot oppo-rock? and
  -rotate-5
  4dup play-paper? -rot oppo-paper? and
  -rotate-5
  play-scissors? -rot oppo-scissors? and
  or or ;

: win? ( oppo-action-string len play-action-string len -- score-u )
  4dup play-rock? -rot oppo-scissors? and
  -rotate-5
  4dup play-paper? -rot oppo-rock? and
  -rotate-5
  play-scissors? -rot oppo-paper? and
  or or ;

: score ( oppo-action-string len play-action-string len -- score-u )
  \ calculate part of score for play choice
  2dup play-rock?
  if
    rock-score -rotate-5
  else
    2dup play-paper?
    if
      paper-score -rotate-5
    else
      2dup play-scissors?
      if
        scissors-score -rotate-5
      then
    then
  then
  \ calculate part of score for round result
  4dup draw?
  if 3 -rotate-5
  else
    4dup win? if 6 -rotate-5 else 0 -rotate-5 then
  then
  4drop
  + ;



8 Constant max-bytes-line
Create line-buffer max-bytes-line 2 + allot

: input-filename s" input" ;
input-filename r/o open-file throw Value puzzle-input-handle

: total-score ( c-addr length -- ??? )
  0  \ accumulator value for score
  begin puzzle-input-handle file-eof? not
  while
    \ read lines until the file has been completely processed
    line-buffer max-bytes-line puzzle-input-handle read-line throw  \ stack: acc length eof-flag

    \ check that everything was read OK from the line buffer
    swap dup 0 > rot and
    \ stack: acc length eof-flag
    \ stack: acc eof-flag length
    \ stack: acc eof-flag length length
    \ stack: acc eof-flag length length 0
    \ stack: acc eof-flag length length>0-flag
    \ stack: acc length length>0-flag eof-flag
    \ stack: acc length both-ok-flag
    if
      line-buffer swap  \ acc c-addr length
      \ split string into the 2 parts at the space character
      BL $split  \ acc c-addr-part-1 length-part-1 c-addr-part-2 length-part-2
      \ add up the score
      score +
      .s cr
    then
  repeat
  \ drop length of read characters from EOF read
  drop
  .s cr ;

total-score .
